#include <iostream>
#include <pthread.h>
#include <string>
#include <unistd.h>

using namespace std;

volatile bool quit = false;
#define TNUM 4

typedef void (*func_t)(const std::string& name, pthread_mutex_t* pmtx, pthread_cond_t* pcond);

class ThreadData
{
public:
    ThreadData(const std::string& name, func_t func, pthread_mutex_t* pmtx, pthread_cond_t* pcond)
        :
        _name(name),
        _func(func),
        _pmtx(pmtx),
        _pcond(pcond)
    {}

public:
    std::string _name;
    func_t _func;
    pthread_mutex_t* _pmtx;
    pthread_cond_t* _pcond;
};

void func1(const std::string& name, pthread_mutex_t* pmtx, pthread_cond_t* pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);
        //wait一定要在加锁和解锁之间wait
        //检测临界资源是否就绪，如果临界资源没有就绪，就等待
        pthread_cond_wait(pcond, pmtx);//默认该线程在执行的时候，wait代码被执行，当前线程会被立即被阻塞
        cout << name << " running -- a" << endl;
        pthread_mutex_unlock(pmtx);
    }
}

void func2(const std::string& name, pthread_mutex_t* pmtx, pthread_cond_t* pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcond, pmtx);
        cout << name << " running -- b" << endl;
        pthread_mutex_unlock(pmtx);
    }
}

void func3(const std::string& name, pthread_mutex_t* pmtx, pthread_cond_t* pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcond, pmtx);
        cout << name << " running -- c" << endl;
        pthread_mutex_unlock(pmtx);
    }
}

void func4(const std::string& name, pthread_mutex_t* pmtx, pthread_cond_t* pcond)
{
    while (!quit)
    {
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcond, pmtx);
        cout << name << " running -- d" << endl;
        pthread_mutex_unlock(pmtx);
    }
}

void* Entry(void* args)
{
    ThreadData* td = (ThreadData*)args;//td在每个线程中自己的私有栈空间里保存
    td->_func(td->_name, td->_pmtx, td->_pcond);//是一个函数，调用完要返回
    delete td;
    return nullptr;
}

int main()
{
    //定义锁和条件变量
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    //初始化锁和条件变量
    pthread_mutex_init(&mtx, nullptr);
    pthread_cond_init(&cond, nullptr);

    pthread_t tids[TNUM];
    func_t funcs[TNUM] = { func1, func2, func3, func4 };
    for (int i = 0; i < TNUM; i++)
    {
        std::string name = "thread ";
        name += to_string(1 + i);
        ThreadData* td = new ThreadData(name, funcs[i], &mtx, &cond);
        pthread_create(tids + i, nullptr, Entry, (void*)td);
    }

    sleep(5);
    
    //主线程唤醒新线程执行不同的任务
    int cnt = 10;
    while (cnt)
    {
        cout << "resume new thread run ..."  << cnt-- << endl;
        //pthread_cond_signal(&cond);
        pthread_cond_broadcast(&cond);
        sleep(1);
    }
    quit = true;
    pthread_cond_broadcast(&cond);
    
    for (int i = 0; i < TNUM; i++)
    {
        pthread_join(tids[i], nullptr);
        cout << "thread " << tids[i] << " quit" << endl;
    }

    //销毁锁和条件变量
    pthread_mutex_destroy(&mtx);
    pthread_cond_destroy(&cond);
    
    return 0;
}